import base64
import json
import pickle
from django import http
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection
from goods.models import SKU
from meiduo.utils.response_code import RET


class CartView(View):
    def post(self, request):
        # 1,获取参数
        dict_data = json.loads(request.body.decode())
        sku_id = dict_data.get("sku_id")
        count = dict_data.get("count")
        selected = dict_data.get("selected", True)

        # 2,校验参数
        # 2,1 为空校验
        if not all([sku_id, count]):
            return http.JsonResponse({"code": RET.PARAMERR, "errmsg": "参数不全"}, status=400)

        # 2,2 将count转整数
        try:
            count = int(count)
        except Exception as e:
            return http.JsonResponse({"code": RET.PARAMERR, "errmsg": "count有误"}, status=400)

        # 2,3 判断sku_id对象是否存在
        try:
            sku = SKU.objects.get(id=sku_id)
        except Exception as e:
            return http.JsonResponse({"code": RET.NODATA, "errmsg": "sku不存在"}, status=400)

        # 2,4 判断库存是否足够
        if count > sku.stock:
            return http.JsonResponse({"code": RET.NODATA, "errmsg": "库存不足"}, status=400)

        # 3,数据入库
        user = request.user
        if user.is_authenticated:
            # 3,1,获取redis对象
            redis_conn = get_redis_connection("cart")

            # 3,2 添加数据到购物车
            redis_conn.hincrby("cart_%s" % user.id, sku_id, count)

            # 3,3 判断选中状态
            if selected:
                redis_conn.sadd("selected_%s" % user.id, sku_id)

            # 3,4 返回响应
            return http.JsonResponse({"code": RET.OK})
        else:
            # 4,1获取cookie购物车数据
            cookie_cart = request.COOKIES.get("cart")

            # 4,2 转换成字典
            cookie_cart_dict = {}
            if cookie_cart:
                cookie_cart_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 4,3 添加数据到字典中,需要判断原来的数量
            if sku_id in cookie_cart_dict:
                old_count = cookie_cart_dict[sku_id]["count"]
                count += old_count

            cookie_cart_dict[sku_id] = {
                "count": count,
                "selected": selected
            }

            # 4,4 将字典转成字符串,返回
            cookie_cart = base64.b64encode(pickle.dumps(cookie_cart_dict)).decode()
            response = http.JsonResponse({"code": RET.OK})
            response.set_cookie("cart", cookie_cart)
            return response

    # 获取购物车
    def get(self, request):

        user = request.user
        if user.is_authenticated:
            # 登录用户购物车数据显示
            # 1.获取redis中的购物车数据
            redis_conn = get_redis_connection("cart")
            cart_dict = redis_conn.hgetall("cart_%s" % user.id)
            selected_list = redis_conn.smembers("selected_%s" % user.id)
            # 2.拼接数据
            # 定义用于存放购物车商品的列表
            sku_list = []
            # 循环取出每个商品
            for sku_id, count in cart_dict.items():
                sku = SKU.objects.get(id=sku_id)
                # 拼装数据
                sku_dict = {
                    "id": int(sku_id.decode()),
                    "default_image_url": sku.default_image_url.url,
                    "name": sku.name,
                    "count": int(count),
                    "price": str(sku.price),
                    "selected": str(sku_id in selected_list),
                    "amount": str(sku.price * int(count))
                }
                # 将每个购物车的商品追加到商品列表中
                sku_list.append(sku_dict)

            # 3. 返回响应
            return render(request, 'cart.html', context={"sku_list": sku_list})
        else:
            # 未登录用户购物车数据显示
            # 1. 获取cookie
            cookie_cart = request.COOKIES.get("cart")
            # 2. 将cookie转为字典形式
            # 定义空字典存储
            cookie_cart_dict = {}
            if cookie_cart:
                cookie_cart_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))
            # 3. 拼接数据
            # 定义存放购物车商品的列表
            sku_list = []
            # 循环取出每个商品
            for sku_id, selected_count in cookie_cart_dict.items():
                sku = SKU.objects.get(id=sku_id)
                # 拼接数据
                sku_dict = {
                    "id": sku.id,
                    "selected": str(selected_count["selected"]),
                    "default_image_url": sku.default_image_url.url,
                    "name": sku.name,
                    "price": str(sku.price),
                    "count": int(selected_count["count"]),
                    "amount": str(sku.price * int(selected_count["count"]))
                }
                sku_list.append(sku_dict)
            # 4. 返回响应
            return render(request, 'cart.html', context={"sku_list": sku_list})

    # 修改购物车
    def put(self, request):
        # 1.获取参数
        # 将获取的json数据转为字典形式
        dict_data = json.loads(request.body.decode())
        # 获取前端传过来的数据
        sku_id = dict_data.get("sku_id")
        count = dict_data.get("count")
        selected = dict_data.get("selected", True)

        # 2.校验数据
        # 为空检验
        if not all([sku_id, count]):
            return http.JsonResponse({"code": RET.PARAMERR, "errmsg": "参数不足"}, status=400)
        # 校验商品是否存在
        try:
            sku = SKU.objects.get(id=sku_id)
        except Exception:
            return http.JsonResponse({"code": RET.NODATA, "errmsg": "商品不存在"}, status=400)
        # 将count转成整数
        try:
            count = int(count)
        except Exception:
            # 传入的count不是数字则提示错误信息
            return http.JsonResponse({"code": RET.PARAMERR, "errmsg": "参数错误"}, status=400)
        # 校验库存是否充足
        if count > sku.stock:
            return http.JsonResponse({"code": RET.NODATA, "errmsg": "库存不足"}, status=400)

        # 3.数据入库(redis/cookie)
        user = request.user
        if user.is_authenticated:
            # 登录用户购物车数据入库(redis)
            # 获取redis对象
            redis_conn = get_redis_connection("cart")
            # 设置数据,数据入库
            # 存入到哈希cart_userid中
            redis_conn.hset("cart_%s" % user.id, sku_id, count)
            # 存入到集合selected_userid中
            if selected:
                redis_conn.sadd("selected_%s" % user.id, sku_id)
            else:
                redis_conn.srem("selected_%s" % user.id, sku_id)
            # 拼接数据返回给前端更新购物车
            sku_dict = {
                "id": sku.id,
                "selected": selected,
                "default_image_url": sku.default_image_url.url,
                "name": sku.name,
                "price": str(sku.price),
                "count": count,
                "amount": str(sku.price * count)
            }
            # 返回响应
            return http.JsonResponse({"code": RET.OK, "cart_sku": sku_dict})

        else:
            # 未登录用户购物车数据入库(cookie)
            # 取出cookie数据
            # 获取cookie对象
            cookie_cart = request.COOKIES.get("cart")
            # 将cookie转为字典
            cookie_cart_dict = {}
            if cookie_cart:
                cookie_cart_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))
            # 将获取的数据写入到cookie中(修改cookie数据)
            cookie_cart_dict[sku_id] = {
                "count": count,
                "selected": selected
            }
            # 拼接数据返回响应
            sku_dict = {
                "id": sku.id,
                "default_image_url": sku.default_image_url.url,
                "name": sku.name,
                "price": str(sku.price),
                "count": count,
                "selected": selected,
                "amount": str(sku.price * count)
            }
            response = http.JsonResponse({"code": RET.OK, "cart_sku": sku_dict})
            # 更新cookie数据
            cookie_cart = base64.b64encode(pickle.dumps(cookie_cart_dict)).decode()
            response.set_cookie("cart", cookie_cart)
            return response

    def delete(self, request):
        # 1,获取参数
        dict_data = json.loads(request.body.decode())
        sku_id = dict_data.get("sku_id")

        # 2,校验参数
        # 2,1 为空校验
        if not sku_id:
            return http.JsonResponse({"code": RET.PARAMERR,
                                      "errmsg": "参数不全"}, status=400)

        # 2,2 判断sku对象是否存在
        try:
            sku = SKU.objects.get(id=sku_id)
        except Exception as e:
            return http.JsonResponse({"code": RET.PARAMERR,
                                      "errmsg": "商品不存在"}, status=400)

        # 3,数据入库(删除)
        user = request.user
        if user.is_authenticated:
            # 3,1 删除redis数据
            redis_conn = get_redis_connection("cart")
            redis_conn.hdel("cart_%s" % user.id, sku_id)
            redis_conn.srem("selected_%s" % user.id, sku_id)

            # 3,2,返回响应
            return http.JsonResponse({"code": RET.OK})
        else:
            # 4,1 获取cookie数据
            cookie_cart = request.COOKIES.get("cart")

            # 4,2 数据转换
            cookie_cart_dict = {}
            if cookie_cart:
                cookie_cart_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 4,3 删除数据
            if sku_id in cookie_cart_dict:
                del cookie_cart_dict[sku_id]

            # 4,4 设置cookie数据,返回响应
            response = http.JsonResponse({"code": RET.OK})
            cookie_cart = base64.b64encode(pickle.dumps(cookie_cart_dict)).decode()
            response.set_cookie("cart", cookie_cart)
            return response


class CartsAllSelectView(View):
    def put(self, request):
        # 1,获取参数
        dict_data = json.loads(request.body.decode())
        selected = dict_data.get("selected")

        # 2,校验参数
        try:
            selected = bool(selected)
        except Exception as e:
            return http.JsonResponse(status=400)

        # 3,数据入库
        user = request.user
        if user.is_authenticated:
            # 3,1获取redis
            redis_conn = get_redis_connection("cart")

            # 3,2修改数据
            cart_dict = redis_conn.hgetall("cart_%s" % user.id)
            sku_ids = cart_dict.keys()

            if selected:
                redis_conn.sadd("selected_%s" % user.id, *sku_ids)
            else:
                redis_conn.srem("selected_%s" % user.id, *sku_ids)

            # 3,3返回响应
            return http.JsonResponse({"code": RET.OK})
        else:
            # 4,1 获取参数
            cookie_cart = request.COOKIES.get("cart")

            # 4,2 数据转换
            cookie_cart_dict = {}
            if cookie_cart:
                cookie_cart_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 4,3 修改数据
            for sku_id, selected_count in cookie_cart_dict.items():
                selected_count["selected"] = selected

            # 4,4 转换数据,返回响应
            response = http.JsonResponse({"code": RET.OK})
            cookie_cart = base64.b64encode(pickle.dumps(cookie_cart_dict)).decode()
            response.set_cookie("cart", cookie_cart)
            return response


class CartsSimpleView(View):
    def get(self, request):
        # 1,获取用户
        user = request.user

        # 2,判断用户登陆状态
        if user.is_authenticated:
            # 2,1 获取redis数据
            redis_conn = get_redis_connection("cart")
            cart_dict = redis_conn.hgetall("cart_%s" % user.id)

            # 2,2 拼接数据
            sku_list = []
            for sku_id, count in cart_dict.items():
                sku = SKU.objects.get(id=sku_id)
                sku_dict = {
                    "id": sku.id,
                    "default_image_url": sku.default_image_url.url,
                    "name": sku.name,
                    "count": int(count)
                }
                sku_list.append(sku_dict)

            # 2,3 返回响应
            return http.JsonResponse({"cart_skus": sku_list})
        else:
            # 3,1 获取cookie数据
            cookie_cart = request.COOKIES.get("cart")

            # 3,2 数据转换
            cookie_cart_dict = {}
            if cookie_cart:
                cookie_cart_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 3,3 数据拼接
            sku_list = []
            for sku_id, seleted_count in cookie_cart_dict.items():
                sku = SKU.objects.get(id=sku_id)
                sku_dict = {
                    "id": sku.id,
                    "default_image_url": sku.default_image_url.url,
                    "name": sku.name,
                    "count": int(seleted_count["count"])
                }
                sku_list.append(sku_dict)

            # 4,4 返回响应
            return http.JsonResponse({"cart_skus": sku_list})
